function textClass(id) {
    this.wordsLen = 1;
    this.currWordIndex = 1;
    this.id = id;
    this.readPara = function() {
        var id = this.id;
        this.resetText();
        this.wordsLen = $("#"+id+" span").length;
        this.highlightWord(this.currWordIndex)
    };
    this.highlightWord = function(a) {
        var id = this.id;
        $("#"+id+" span.green").removeClass("green");
        $("#"+id+" span:nth-child(" + (parseInt(a)) + ")").addClass("green")
    };
    this.getWord = function(a) {
        var b = $("#"+this.id+" span:nth-child(" + (parseInt(a)) + ")").text();
        return b
    };
    this.nextWord = function() {
        if (this.currWordIndex < this.wordsLen) {
            this.currWordIndex++;
            this.highlightWord(this.currWordIndex)
            return true;
        } else {
            return false;
        }
    };
    this.paraOver = function() {
        return (this.currWordIndex >= this.wordsLen);
    };
    this.resetText = function() {
        this.currWordIndex = 1;
        $("#"+this.id+" span.green").removeClass("green");
        $("#"+this.id+" span.red").removeClass("red")
    };
    this.indicateWrong = function(a) {
        a = typeof a !== "undefined" ? a : false;
        if (a) {
            $("#"+this.id+" span.green").addClass("red")
        } else {
            $("#"+this.id+" span.green").removeClass("red")
        }
    }
    this.getProgress = function() {
        //if(this.currWordIndex == this.wordsLen) return 100;
        return parseInt((this.currWordIndex-1)/this.wordsLen*100);
    }
}
/* the timer works in such a way that the minimum increment time is 1/10th of a second */
function timerClass() {
    this.timer = null;
    this.timerVal = 0;
    this.callBack;
    this.limit = 1000; // limit is 100 seconds
    this.scopeObj;
    this.startTimer = function(scope, cb, limit) {
        var t = this;
        t.timerVal = 0;
        t.limit = parseInt(limit, 10) || 10000; // limit 0f  a 1000 seconds
        t.callBack = cb;
        t.scopeObj = scope;
        t.timer = window.setInterval(function() { t.incrementTimer(); }, 100);
    };
    this.endTimer = function() {
        clearInterval(this.timer);
    };
    this.incrementTimer = function() {
        var t = this;
        t.timerVal++;
        if (t.timerVal >= t.limit)
            t.endTimer();
        t.callBack.call(t.scopeObj, t.timerVal);
    };
}

function gameClass(text_id, input_id, msg_id, button, trackid, no_submit) {
    this.timeElapsed = 0;
    this.timerObj = new timerClass();
    this.textObj = new textClass(text_id);
    this.input_id = input_id;
    this.msg_id = msg_id;
    this.button = button;
    this.trackid = trackid;
    this.status = "off";
    this.no_submit = no_submit || false;
    this.top_margin = 0;
    this.countdown_limit = parseInt(configObj.countdown_limit, 10)*10;

    this.initGame = function() {
        this.timerObj.startTimer(this, this.countDownCallBack, this.countdown_limit);
    };
    this.countDownCallBack = function(t) {
        var time_left = this.countdown_limit - t;
        if(time_left == 0) {
            $('#countdownlayerbg, #countdownlayer').addClass('hid');
            this.startGame();
        } else {
            $('#countdownlayerbg, #countdownlayer').removeClass('hid');
            $('#countdownlayer').text(parseInt(time_left/10, 10)+1);
        }
    };
    this.startGame = function() {
        var t = this;
        t.textObj.readPara();
        t.timerObj.startTimer(t, t.timerCallBack);
        $("#"+t.input_id).removeAttr("disabled").val("").focus();
        if($("#"+t.button).length > 0) $("#"+t.button).text("stop!");
        t.handlePositioning();
        t.handleProgress();
        t.timeElapsed = 0;
        t.status = "on";
    };
    this.showMessage = function(a, b) {
        if (a === true) {
            $("#"+this.msg_id).show();
            if (b)
                $("#"+this.msg_id).html(b);
        } else if (a === false) {
            $("#"+this.msg_id).hide()
        }
    };
    this.showTimeInMessage = function(a) {
        if(typeof a =='undefined')
            a = this.timeElapsed/10;
        this.showMessage(true, String(a)); 
    };
    this.timerCallBack = function(t) {
        this.timeElapsed = t;
        this.showTimeInMessage();
    };
    this.handleChange = function(key) {
        var a = this.textObj.getWord(this.textObj.currWordIndex);
        var b = $("#"+this.input_id).val();
        b = b.trim();

        if(this.textObj.paraOver() && b==a) {
            this.endGame();
            return;
        } 

        if (b != a.substr(0, b.length)) {
            this.textObj.indicateWrong(true)
        } else this.textObj.indicateWrong(false);

        if(typeof key!='undefined' && (key == 13 || key == 32)) {
            if (b == a) {
                $("#"+this.input_id).val("");
                this.textObj.nextWord();
                this.handlePositioning();
                this.handleProgress();
            }
        }
    };
    this.handlePositioning = function() {
        var top, bottom, margin;
        if($('#'+this.trackid).find('span.green').length > 0) {
            top = $('#'+this.trackid).find('span.green').position().top;
            bottom = $('#'+this.trackid).height() - top;
        }
        if(typeof top!='undefined' && top > 100 && bottom > 80) {
            margin = parseInt(top-100);
            if(margin!=this.top_margin) {
                $('#'+this.trackid).animate({'margin-top': '-'+margin+'px'}, 500);
                this.top_margin = margin;
            }  
        } else {
            margin = Math.abs(this.top_margin);
            if(typeof top!= 'undefined' && top < 100 && margin!=0) {
                $('#'+this.trackid).animate({'margin-top': '0px'});
                this.top_margin = 0;
                margin = 0;
            }
        }
        if(margin+200 < $('#'+this.trackid).height()) {
            $('#'+this.trackid+'bs').show();
        } else $('#'+this.trackid+'bs').hide();

        if(margin > 0) {
            $('#'+this.trackid+'ts').show();
        } else $('#'+this.trackid+'ts').hide();
    };

    var t = this;
    if($('#'+this.button).length > 0) {
        $("#"+this.button).text("start");
        $("#"+this.button).bind("click", function() {
            if(t.status == 'off') { 
                if(!t.no_submit && document.cookie.indexOf('tr_username')==-1) {
                   $('#username').click(); 
                }
                t.initGame()
            } else {
                t.endGame(true);
            }
        });
    }
    $("#"+this.input_id).val("").attr("disabled", "disabled");
    $("#"+this.input_id).bind("keyup keypress", function(e) { 
        var key = e.which || e.charCode;
        t.handleChange(key); 
    });
};

gameClass.prototype.handleProgress = function() {
    var progress;
    if(typeof complete!='undefined' && complete) {
        progress = 100;
    } else {
        progress = this.textObj.getProgress();
    }
    $('#'+this.trackid+"progress").css('width', progress+'%');
};
gameClass.prototype.endGame = function(unfinished) {
    a = (typeof unfinished !== "undefined") ? unfinished : false;
    this.showTimeInMessage();
    this.textObj.resetText();
    $("#"+this.input_id).val("").attr("disabled", "disabled");
    if($("#"+this.button).length > 0) $("#"+this.button).text("start!");
    this.timerObj.endTimer();
    if (!a && !this.no_submit) {
        ajaxObj.submitScore(this.timeElapsed);
    }
    this.handleProgress(true);
    this.status = "off";
};

var layerObj = new function() {
    this.show = function(txt, parentId) {
        this.closeAll();
        var parentPositions = $('#' + parentId).position();
        var parentWidth = $('#' + parentId).width();
        var $dialog = $('<div id="layerObj" class="box-shadow"></div>').html(txt).appendTo('body').css('left', parentPositions.left+parentWidth).css('top', parentPositions.top);
    }
    this.closeAll = function() {
        $('#layerObj').remove();
    }
};


var ajaxObj = new function () {
    this.submitScore = function (a) {
        if (!a) {
            return false
        }
        var b = $("#username").text();
        if (!b) {
            alert("You ain't got no name?");
            return false;
        }
        $("#messageDiv").show().text("submitting score");
        $.post(configObj.backendUrl+"/submitScore", {
            blah: a,
            name: b
        }, function (d) {
            var c = JSON.parse(d);
            if (!c.s) {
                alert("something went wrong!");
                gameObj.showMessage("", false)
            } else {
                ajaxObj.updateScoreTable()
            }
            $("#messageDiv").hide().text("")
        });
        return false
    };
    this.updateScoreTable = function () {
        $('#messageDiv').text("updating score table..");
        $.post(configObj.backendUrl+"/fetchScore", function (b) {
            var a = JSON.parse(b);
            if (a.status == 1) {
                $("#scoreTable").html(a.content)
            } else {
                $("#scoreTable").html(a.content)
            }
            $('#messageDiv').text("");
        })
    };
    this.longPollRoom = function() {
        $.get(configObj.backendUrl+"/roomPing", { room_id : roomData.room_id, mod : roomData.mod },
            function (b) {
                var a = JSON.parse(b);
                if(a['s']) {
                    if(a['d']) {
                        roomData.mod = a['mod'];
                        roomData.players = a['info'];
                        room_showPlayers();
                        room_updateStatus(true);
                    }
                    ajaxObj.longPollRoom();
                } else room_updateStatus(false);
        }).fail(function() {
            room_updateStatus(false);
        });  
    };
    this.markReady = function() {
      $.get(configObj.backendUrl+"/markReady", { room_id : roomData.room_id},
            function(b) {
                var a = JSON.parse(b);
                if(!a['s'])
                room_updateStatus(false);
            }
         ).fail(function() {
            room_updateStatus(false);
        });  
    };
    this.updateProgress = function(progress, time) {
        $.post(configObj.backendUrl+"/updateProgress", { progress : roomData.p, time : roomObj.timeElapsed, room_id : roomData.room_id},
            function(b) {
                var a = JSON.parse(b);
                if(!a['s'])
                    room_updateStatus(false);
            }
         ).fail(function() {
            room_updateStatus(false);
        });  
    };
};



function setCookie(c_name,value,exdays)
{
    var exdate=new Date();
    exdate.setDate(exdate.getDate() + exdays);
    var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
    document.cookie=c_name + "=" + c_value;
}
